#include <stdlib.h>
#include <string.h>
#include "driver/rmt_common.h"
#include "driver/rmt_encoder.h"
#include "driver/rmt_types.h"
#include "driver/rmt_tx.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

// 声明区
#define GPIO_NUM CONFIG_BLINK_GPIO             // 引脚号
#define TICK_FREQ 10 * 1000000 // 频率
#define LED_NUM 1             // 灯珠数目
// #define DELAY_MS 20            // 延时

// 将RGB转为GRB整数
#define COLOR_U32(r, g, b) ( \
    (uint32_t)g << 16 |      \
    (uint32_t)r << 8 |       \
    (uint32_t)b)

// 变量区
/* 发送通道 */
static rmt_channel_handle_t txChannel;
/* 编码器 */
static rmt_encoder_handle_t rfEncoder;
/* 消息符号 */
static rmt_symbol_word_t zeroSymbol, oneSymbol, resetSymbol;
/* 要传输的颜色数据 */
static rmt_symbol_word_t rgbSymbols[24 * LED_NUM] = {0};

/************* 自定义函数 ******************/
void init_tx_channel()
{
    rmt_tx_channel_config_t cfg = {
        // GPIO
        .gpio_num = GPIO_NUM,
        // 时钟源：默认是APB
        .clk_src = RMT_CLK_SRC_DEFAULT,
        // 分辨率，即频率
        .resolution_hz = TICK_FREQ,
        // 内存大小，指的是符号个数，不是字节个数
        .mem_block_symbols = 64,
        // 传输队列深度，不要设得太大
        .trans_queue_depth = 4
        // 禁用回环（自己发给自己）
        //.flags.io_loop_back=0
    };
    // 调用函数初始化
    ESP_ERROR_CHECK(rmt_new_tx_channel(&cfg, &txChannel));
}

/* 初始化符号 */
void init_symbols()
{
    // 0码高电平
    zeroSymbol.duration0 = 0.4 * (TICK_FREQ / 1000000);
    zeroSymbol.level0 = 1;
    // 0码低电平
    zeroSymbol.duration1 = 0.8 * (TICK_FREQ / 1000000);
    zeroSymbol.level1 = 0;

    // 1码高电平
    oneSymbol.duration0 = 0.8 * (TICK_FREQ / 1000000);
    oneSymbol.level0 = 1;
    // 1码低电平
    oneSymbol.duration1 = 0.4 * (TICK_FREQ / 1000000);
    oneSymbol.level1 = 0;

    // 复位信号全为低电平
    resetSymbol.duration0 = 25 * (TICK_FREQ / 1000000);
    resetSymbol.level0 = 0;
    resetSymbol.duration1 = 25 * (TICK_FREQ / 1000000);
    resetSymbol.level1 = 0;
}

/* 初始化编码器 */
void init_encoder()
{
    // 目前配置不需要参数
    rmt_copy_encoder_config_t cfg = {};
    // 创建拷贝编码器
    ESP_ERROR_CHECK(rmt_new_copy_encoder(&cfg, &rfEncoder));
}

/* 设置颜色 */
void set_rgb(int index, uint32_t grb)
{
    if (index < 0 || index > LED_NUM - 1)
    {
        return; // 索引无效
    }
    // 循环的开始和结束索引
    int startIdx = index * 24;
    int endIdx = startIdx + 24;
    for (int i = startIdx; i < endIdx; i++)
    {
        if (grb & 0x00800000)
        {
            // 1
            rgbSymbols[i] = oneSymbol;
        }
        else
        {
            // 0
            rgbSymbols[i] = zeroSymbol;
        }
        // 左移一位
        grb <<= 1;
    }
}

/* 发送数据 */
void send_data()
{
    // 配置
    rmt_transmit_config_t cfg = {
        // 不要循环发送
        .loop_count = 0};
    // 发送
    ESP_ERROR_CHECK(rmt_transmit(txChannel, rfEncoder, rgbSymbols, sizeof(rgbSymbols), &cfg));
    // 等待发送完毕
    // ESP_ERROR_CHECK(rmt_tx_wait_all_done(txChannel, portMAX_DELAY));
    // 发送复位信号
    ESP_ERROR_CHECK(rmt_transmit(txChannel, rfEncoder, &resetSymbol, 1, &cfg));
    // 等待完成
    ESP_ERROR_CHECK(rmt_tx_wait_all_done(txChannel, portMAX_DELAY));
}

void app_main(void)
{
    // 1、初始化通道
    init_tx_channel();
    // 2、初始化符号
    init_symbols();
    // 3、初始化编码器
    init_encoder();
    // 4、使能通道
    ESP_ERROR_CHECK(rmt_enable(txChannel));

    int i;
    /* 进入循环 */
    while (1)
    {
        // 红色
        for (i = 0; i < LED_NUM; i++)
        {
            set_rgb(i, COLOR_U32(0xff, 0x0, 0x0));
        }
        send_data();
        // 延时
        vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);

        // 蓝色
        for (i = 0; i < LED_NUM; i++)
        {
            set_rgb(i, COLOR_U32(0x0, 0x0, 0xff));
        }
        send_data();
        // 延时
        vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);

        // 绿色
        for (i = 0; i < LED_NUM; i++)
        {
            set_rgb(i, COLOR_U32(0x0, 0xff, 0x0));
        }
        send_data();
        // 延时
        vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);
    }
}